function lazy_sum(arr) {  // 高阶函数 返回 函数, 返回的函数就是 闭包
    var sum = function () { return arr.reduce(function (x, y) { return x + y; }); }
    return sum;
}
var f = lazy_sum([1, 2, 3, 4, 5]); console.log(f, f());  // [Function] 15, 返回的函数并没有立刻执行, 而是直到调用了f()才执行

// 闭包的坑
function count() {
    var arr = [];
    for (var i=1; i<=3; i++) { arr.push(function () { return i * i; }); }  // 创建三个函数, 并把函数都添加到 arr 中
    return arr;
}
var results = count(), f1 = results[0], f2 = results[1], f3 = results[2]; console.log(f1(), f2(), f3());  // 16, 16, 16
// 返回的函数没有立即执行, 直到调用 f() 才执行, 等到三个函数都返回时, i 已经是 4 了
// 返回函数不要引用任何循环变量, 或者后续会发生变化的变量, 否则变量会最后再执行, 跟设计的不太一样
// 或者再创建一个函数, 用该函数的参数绑定循环变量当前的值
function count_1() {  // 如果这个函数命名为 count, 那么会影响到上面的结果
    var arr = [];
    for (var i=1; i<=3; i++) { arr.push((function (n) { return function () { return n * n; } })(i)); }
    return arr;
}
var results = count_1(), f1 = results[0], f2 = results[1], f3 = results[2]; console.log(f1(), f2(), f3());  // 1, 4, 9
console.log((function(x){ return x * x; })(3)); // 9, 上面是因为用到了 ***创建匿名函数并立刻执行的语法***

// 在没有 class 机制, 只有函数的语言里, 借助闭包, 同样可以封装一个私有变量, 创建一个计数器
function create_counter(initial) {
    var x = initial || 0;
    return { inc: function () { x += 1; return x; } }
}
var c2 = create_counter(10); console.log(c2.inc(), c2.inc(), c2.inc());  // 11, 12, 13
// 返回的对象中, 实现了一个闭包, 带了局部变量 x, 外部无法访问到变量 x; 换句话说, 闭包就是携带状态的函数, 并且它的状态可以完全对外隐藏起来
